/*
 * StraightFrameDialog.java
 *
 * Created on Oct 1, 2011, 10:06:00 AM
 */
package com.photoexpert;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

/**
 *
 * @author PANYIXIN
 */
class StraightFrameDialog extends javax.swing.JDialog {

    StraightFrameDialog() {
        super(App.Instance(), true);
        initComponents();
        _table.setDefaultRenderer(Color.class, new ColorRenderer(true));
        _table.setDefaultEditor(Color.class, new ColorEditor());
        setLocation(200, 200);
        setVisible(true);
        _preview.repaint();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        _table = new javax.swing.JTable();
        _previewLabel = new javax.swing.JLabel();
        _preview = new FramePreviewPane();
        _add = new javax.swing.JButton();
        _cancel = new javax.swing.JButton();
        _ok = new javax.swing.JButton();
        _remove = new javax.swing.JButton();
        _keepSize = new javax.swing.JCheckBox();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Straight frame");
        setModal(true);

        _table.setModel(_tableModel);
        jScrollPane1.setViewportView(_table);

        _previewLabel.setText("Preview:");

        javax.swing.GroupLayout _previewLayout = new javax.swing.GroupLayout(_preview);
        _preview.setLayout(_previewLayout);
        _previewLayout.setHorizontalGroup(
            _previewLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 271, Short.MAX_VALUE)
        );
        _previewLayout.setVerticalGroup(
            _previewLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 181, Short.MAX_VALUE)
        );

        _add.setText("Add frame");
        _add.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _addActionPerformed(evt);
            }
        });

        _cancel.setText("Cancel");
        _cancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _cancelActionPerformed(evt);
            }
        });

        _ok.setText("OK");
        _ok.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _okActionPerformed(evt);
            }
        });

        _remove.setText("Remove frame");
        _remove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _removeActionPerformed(evt);
            }
        });

        _keepSize.setText("Keep image size");
        _keepSize.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _keepSizeActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 385, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(_previewLabel)
                            .addComponent(_preview, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(_remove, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(_add, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(_ok, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(_cancel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addComponent(_keepSize))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(_keepSize)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(_add)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(_remove)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
                        .addComponent(_ok)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(_cancel))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(_previewLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(_preview, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void _okActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__okActionPerformed
        int frames = _tableModel.getRowCount();
        BufferedImage img = _implementor.getImage();
        int width = img.getWidth();
        int height = img.getHeight();
        BufferedImage destination;
        Graphics g;
        if(!_keepSize.isSelected()) {
            // create new image because size changed
            int imgType = img.getTransparency() == Transparency.OPAQUE ?
                BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
            int frameWidth = 0;
            for(int i = 0; i < frames; ++i)
                frameWidth += _tableModel._widths.get(i);
            width += frameWidth * 2;
            height += frameWidth * 2;
            destination = new BufferedImage(width, height, imgType);
            g = destination.createGraphics();
            g.drawImage(img, frameWidth, frameWidth, null);
        } else {
            destination = img;
            g = img.createGraphics();
        }
        int x1 = 0;
        for(int i = 0; i < frames; ++i) {
            Color c = _tableModel._colors.get(i);
            Color color = new Color(c.getRed(), c.getGreen(), c.getBlue(),
                _tableModel._alphas.get(i));
            g.setColor(color);
            int frameWidth = _tableModel._widths.get(i);
            g.fillRect(x1, x1, frameWidth, height - x1 * 2);
            g.fillRect(x1, x1, width - x1 * 2, frameWidth);
            g.fillRect(width - x1 - frameWidth, x1, frameWidth, height - x1 * 2);
            g.fillRect(x1, height - x1 - frameWidth, width - x1 * 2, frameWidth);
            x1 += frameWidth;
        }
        g.dispose();
        _implementor.setImage(destination);
        setVisible(false);
        dispose();
    }//GEN-LAST:event__okActionPerformed

    private void _addActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__addActionPerformed
        _tableModel.addRow();
    }//GEN-LAST:event__addActionPerformed

    private void _cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__cancelActionPerformed
        setVisible(false);
        dispose();
    }//GEN-LAST:event__cancelActionPerformed

    private void _removeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__removeActionPerformed
        int row = _table.getSelectedRow();
        if(row >= 0)
            _tableModel.removeRow(row);
    }//GEN-LAST:event__removeActionPerformed

    private void _keepSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__keepSizeActionPerformed
        _preview.repaint();
    }//GEN-LAST:event__keepSizeActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton _add;
    private javax.swing.JButton _cancel;
    private javax.swing.JCheckBox _keepSize;
    private javax.swing.JButton _ok;
    private javax.swing.JPanel _preview;
    private javax.swing.JLabel _previewLabel;
    private javax.swing.JButton _remove;
    private javax.swing.JTable _table;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables
    private FrameTableModel     _tableModel = new FrameTableModel();
    private Implementor         _implementor = Implementor.Instance();

    private class FramePreviewPane extends JPanel {
        @Override
        public void paint(Graphics g) {
            Dimension dimension = _preview.getSize();
            int x3 = dimension.width;
            int y3 = dimension.height;
            int x1 = 0;
            int frames = _tableModel.getRowCount();
            for(int i = 0; i < frames; ++i) {
                Color c = _tableModel._colors.get(i);
                Color color = new Color(c.getRed(), c.getGreen(), c.getBlue(),
                    _tableModel._alphas.get(i));
                int width = _tableModel._widths.get(i);
                g.setColor(color);
                g.fillRect(x1, x1, width, y3 - x1);
                g.fillRect(x1, x1, x3 - x1, width);
                x1 += width;
            }
            int imgWidth = _implementor.getWidth();
            int imgHeight = _implementor.getHeight();
            int imgX1 = x1;
            if(!_keepSize.isSelected()) {
                imgWidth += x1;
                imgHeight += x1;
                imgX1 = 0;
            }
            if(x3 > imgWidth)
                x3 = imgWidth;
            if(y3 > imgHeight)
                y3 = imgHeight;
            BufferedImage img = _implementor.getImage().getSubimage(imgX1, imgX1, x3 - x1, y3 - x1);
            g.drawImage(img, x1, x1, null);
        }
    }

    private class FrameTableModel extends AbstractTableModel {
        private String[]            _columnNames = {"Color", "Width", "Alpha"};
        private ArrayList<Color>    _colors = new ArrayList<Color>();
        private ArrayList<Integer>  _widths = new ArrayList<Integer>();
        private ArrayList<Integer>  _alphas = new ArrayList<Integer>();

        void addRow() {
            _widths.add(10);
            _colors.add(Color.BLACK);
            _alphas.add(255);
            int row = _colors.size();
            fireTableRowsInserted(row - 1, row - 1);
            _preview.repaint();
        }

        void removeRow(int row) {
            _colors.remove(row);
            _widths.remove(row);
            _alphas.remove(row);
            fireTableRowsDeleted(row, row);
            _preview.repaint();
        }

        @Override
        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        @Override
        public void setValueAt(Object value, int row, int col) {
            switch(col) {
                case 0 :
                    _colors.set(row, (Color)value);
                    break;
                case 1 :
                    _widths.set(row, (Integer)value);
                    break;
                case 2 :
                    _alphas.set(row, (Integer)value);
                    break;
            }
            fireTableCellUpdated(row, col);
            _preview.repaint();
        }

        @Override
        public int getRowCount() {
            return _colors.size();
        }

        @Override
        public boolean isCellEditable(int row, int col) {
            return true;
        }

        @Override
        public int getColumnCount() { return 3; }

        @Override
        public String getColumnName(int columnIndex) {
            return _columnNames[columnIndex];
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            switch(columnIndex) {
                case 0 :
                    return _colors.get(rowIndex);
                case 1 :
                    return _widths.get(rowIndex);
                case 2 :
                    return _alphas.get(rowIndex);
            }
            return null;
        }
    }

    static private class ColorRenderer extends JLabel implements TableCellRenderer {
        Border  _unselectedBorder = null;
        Border  _selectedBorder = null;
        boolean _isBordered = true;

        ColorRenderer(boolean isBordered) {
            _isBordered = isBordered;
            setOpaque(true); //MUST do this for background to show up.
        }

        @Override
        public Component getTableCellRendererComponent(
            JTable table, Object color,
            boolean isSelected, boolean hasFocus,
            int row, int column) {
            Color newColor = (Color)color;
            setBackground(newColor);
            if(_isBordered) {
                if(isSelected) {
                    if(_selectedBorder == null) {
                        _selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
                            table.getSelectionBackground());
                    }
                    setBorder(_selectedBorder);
                } else {
                    if(_unselectedBorder == null) {
                        _unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
                            table.getBackground());
                    }
                    setBorder(_unselectedBorder);
                }
            }
            setToolTipText("RGB value: " + newColor.getRed() + ", "
                + newColor.getGreen() + ", " + newColor.getBlue());
            return this;
        }
    }

    static class ColorEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
        Color           _currentColor;
        JButton         _button;
        JColorChooser   _colorChooser;
        JDialog         _dialog;
        protected static final String EDIT = "edit";

        ColorEditor() {
            //Set up the editor (from the table's point of view),
            //which is a button.
            //This button brings up the color chooser dialog,
            //which is the editor from the user's point of view.
            _button = new JButton();
            _button.setActionCommand(EDIT);
            _button.addActionListener(this);
            _button.setBorderPainted(false);

            //Set up the dialog that the button brings up.
            _colorChooser = new JColorChooser();
            _dialog = JColorChooser.createDialog(_button,
                "Pick a Color",
                true,  //modal
                _colorChooser,
                this,  //OK button handler
                null); //no CANCEL button handler
            }

            /**
             * Handles events from the editor button and from
             * the dialog's OK button.
             */
        @Override
        public void actionPerformed(ActionEvent e) {
            if (EDIT.equals(e.getActionCommand())) {
                //The user has clicked the cell, so
                //bring up the dialog.
                _button.setBackground(_currentColor);
                _colorChooser.setColor(_currentColor);
                _dialog.setVisible(true);

                //Make the renderer reappear.
                fireEditingStopped();

            } else { //User pressed dialog's "OK" button.
                _currentColor = _colorChooser.getColor();
            }
        }

        //Implement the one CellEditor method that AbstractCellEditor doesn't.
        @Override
        public Object getCellEditorValue() {
            return _currentColor;
        }

        //Implement the one method defined by TableCellEditor.
        @Override
        public Component getTableCellEditorComponent(JTable table,
            Object value,
            boolean isSelected,
            int row,
            int column)
        {
            _currentColor = (Color)value;
            return _button;
        }
    }
}
